public class RNASecondaryStructure
{
	private String name;
	private int length;
	private String type;
	private String anticodon;
	private int anticodonPosition;
	private float score;
	private String sequence;
	private String structure;

	public RNASecondaryStructure()
	{
	}

	public RNASecondaryStructure(String name, int length, String type,
			String anticodon, int anticodonPosition, float score,
			String sequence, String structure)
	{
		super();
		this.name = name;
		this.length = length;
		this.type = type;
		this.anticodon = anticodon;
		this.anticodonPosition = anticodonPosition;
		this.score = score;
		this.sequence = sequence;
		this.structure = structure;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public int getLength()
	{
		return length;
	}

	public void setLength(int length)
	{
		this.length = length;
	}

	public String getType()
	{
		return type;
	}

	public void setType(String type)
	{
		this.type = type;
	}

	public String getAnticodon()
	{
		return anticodon;
	}

	public void setAnticodon(String anticodon)
	{
		this.anticodon = anticodon;
	}

	public int getAnticodonPosition()
	{
		return anticodonPosition;
	}

	public void setAnticodonPosition(int anticodonPosition)
	{
		this.anticodonPosition = anticodonPosition;
	}

	public float getScore()
	{
		return score;
	}

	public void setScore(float score)
	{
		this.score = score;
	}

	public String getSequence()
	{
		return sequence;
	}

	public void setSequence(String sequence)
	{
		this.sequence = sequence;
	}

	public String getStructure()
	{
		return structure;
	}

	public void setStructure(String structure)
	{
		this.structure = structure;
	}

	// Return error code
	// 0 means Ok
	// 1 lentgh is false.
	public int isValid()
	{

		if (!structureTest())
			return 4;
		else if (length != sequence.length())
		{
			System.out.print("Sequence lenth error : ");
			return 1;
		}
		// Sequence test.
		else if (!sequenceTest())
		{
			return 2;
		} 
		else if (!anticodonTest())
		{
			return 3;
		}

		return 0;
	}

	private boolean structureTest()
	{
		if (structure.isEmpty())
		{
			System.out.print("Structure string is empty ;");
			return false;
		}
		if (structure.length() < sequence.length())
		{
			System.out.print("structure length < sequence length");
			return false;
		}
			if (structure.length() > sequence.length())
		{
			structure = structure.substring(0, sequence.length());
		}

		return true;
	}

	// Return true if anticodonPosition is valid.
	private boolean anticodonTest()
	{
		// L'anticodon is ACGT
		if (anticodon.isEmpty())
		{
			System.out.print("Anticodon is unspecified : ");
			return false;
		}
			if (!isACGT(anticodon))
			{
				System.out.print("Anticodon is unspecified : ");
				return false;
			}

		// Anticodon at exact position.
		else if (anticodon.compareTo(sequence.substring(anticodonPosition,
				anticodonPosition + 3)) == 0)
		{
			return true;
		} else
		{
			int mul = -1;
			int shift = 1;
			for (int i = 0; i < 4; i++)
			{
				if (i == 2)
					shift = 2;
				shift *= mul;
				if (anticodon.compareTo(sequence.substring(anticodonPosition
						+ shift, anticodonPosition + shift + 3)) == 0)
				{
					anticodonPosition += shift;
					return true;
				}
			}
		}
		System.out.print("Struture error : ");
		return false;
	}

	// return true if sequence is valid.
	private boolean sequenceTest()
	{
		if (sequence.isEmpty())
			return false;
		sequence = sequence.toUpperCase();
		return isACGT(sequence);
	}

	private boolean isACGT(String k)
	{
		for (int i = 0; i < k.length(); i++)
		{
			if (!(k.charAt(i) == 'A' || k.charAt(i) == 'C'
					|| k.charAt(i) == 'G' || k.charAt(i) == 'T'))
			{
				return false;
			}

		}
		return true;
	}

	public String getFormatInformation(int min, int max)
	{
		String result = new String("\"" + name + "\";" + length + ";" + type
				+ ";" + anticodon + ";" + anticodonPosition + ";\"" + sequence
				+ "\";\"" + structure + "\";" + score + ";");
		result += getFormatInfoCutTri(min, max, 0, false);
		result += getFormatInfoCutTri(min, max, 1, false);
		result += getFormatInfoCutTri(min, max, 2, false);
		result += getFormatInfoCutTri(min, max, 0, true);
		result += getFormatInfoCutTri(min, max, 1, true);
		result += getFormatInfoCutTri(min, max, 2, true);
		return result;
	}

	private String getFormatInfoCutTri(int min, int max, int shift, boolean useX)
	{
		String result = new String();
		result += ";";
		for (int i = min; i <= max; i++)
		{
			if (useX)
				result += CONSTANT.Xset(getTrinucleotide(i, shift, 3, useX)) + ";";
			else
				result += getTrinucleotide(i, shift, 3, useX) + ";";
		}
		return result;
	}

	public void getMinMax(int[] min_max)
	{
		boolean loop = true;
		for (int i = 0; loop; i--)
		{
			// System.out.println(i + "  ");
			if (getTrinucleotide(i, 0, 3, false).isEmpty())
			{
				if (min_max[0] > (i + 1))
				{
					min_max[0] = i + 1;
				}
				loop = false;
			}
		}
		loop = true;
		for (int i = 0; loop; i++)
		{
			if (getTrinucleotide(i, 0, 3, false).isEmpty())
			{
				if (min_max[1] < (i - 1))
				{
					min_max[1] = i - 1;
				}
				loop = false;
			}
		}
	}

	public String getTrinucleotide(int relativePosition, int shift, int taille, boolean useX)
	{		
		relativePosition = anticodonPosition + relativePosition*3 + shift;
		//System.out.println("Seq " +sequence+ " " + relativePosition + " " + length);
		
		if( relativePosition < 0 || ((relativePosition+taille) >= length))
		{	return new String();	}
		else if( useX )	return CONSTANT.Xset(sequence.substring(relativePosition, relativePosition+taille));
		else return sequence.substring(relativePosition, relativePosition+taille);	

	}

	public void display()
	{
		System.out.println(name + " length : " + length);
		System.out.println(" type : " + type + "   Anticodon : " + anticodon
				+ " at " + anticodonPosition + "   Score : " + score);
		System.out.println(" Seq : " + sequence);
		System.out.println(" Str : " + structure);

	}

}
